Problem s NetApi32.dll na Win 9X! WAS: Jak zjistit informace o aktualnim uzivateli?

Otázka od: Ing. Igor Vodicka

26. 8. 2004 9:15

         aktualnim uzivateli?
Podle predesleho sub. jsem provedl nasledujici upravu:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  JclSecurity, StdCtrls, JclSysInfo;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    L_username: TLabel;
    L_privilege: TLabel;
    ListBox1: TListBox;
    Label3: TLabel;
    Label4: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    NetLocalGroupGetMembers: function (
        servername: PWideChar;
        localgroupname: PWideChar;
        level: DWORD;
        var bufptr: Pointer;
        prefmaxlen: DWORD;
        var entriesread: DWORD;
        var totalentries: DWORD;
        var resumehandle: DWORD): Integer; stdcall;
    NetUserGetInfo: function (
        servername: PWideChar;
        localgroupname: PWideChar;
        level: DWORD;
        var bufptr: Pointer): Integer; stdcall;
    NetApiBufferFree: function (buffer: Pointer): Integer; stdcall;
    NetApiDllHandle: HWND;
  public
    { Public declarations }
  end;

type
  PLOCALGROUP_MEMBERS_INFO_1 = ^LOCALGROUP_MEMBERS_INFO_1;
  LOCALGROUP_MEMBERS_INFO_1 = record
    lgrmi1_sid: PSID;
    lgrmi1_sidusage: SID_NAME_USE;
    lgrmi1_name: LPWSTR;
  end;

function GetEnvVar(const Name:String):String;

var
  Form1: TForm1;
  ListUsers,ListGroups: TStringList;

implementation

{$R *.DFM}

procedure GetLocalGroupUsers(lpwServer, lpwGroup : PWideChar);
type
  TUserArray = array of LOCALGROUP_MEMBERS_INFO_1;
var
  pBuffer: Pointer;
  cbRead,cbTotal,Res,hRes: Cardinal;
  i: Integer;
  UserName: PWideChar;
begin
  hRes := 0;
  repeat
    Res := Form1.NetLocalGroupGetMembers(lpwServer, lpwGroup, 1, pBuffer,
1024, cbRead, cbTotal, hRes);
    if (Res = 0) or (Res = ERROR_MORE_DATA) then
    begin
      for i := 0 to cbRead-1 do
      begin
        UserName := TUserArray(pBuffer)[i].lgrmi1_name;
        Form1.ListBox1.Items.Add(WideCharToString(lpwGroup)+':'+UserName);
        ListUsers.Add(UserName);
        ListGroups.Add(WideCharToString(lpwGroup));
      end;
      Form1.NetApiBufferFree(pBuffer);
    end;
  until Res<>ERROR_MORE_DATA;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  L_username.Caption := GetEnvVar('USERNAME');
  Label3.Caption := GetWindowsVersionString;
  case Win32Platform of
    VER_PLATFORM_WIN32_WINDOWS: Label4.Caption := 'Win 9X, ME';
    VER_PLATFORM_WIN32_NT:
    begin
      NetApiDllHandle := LoadLibrary(PChar('NETAPI32.DLL'));
      if NetApiDllHandle <>0 then
      begin
        Label4.Caption := 'Win NT, 2K, XP';
        @NetLocalGroupGetMembers :=
GetProcAddress(NetApiDllHandle,'NetLocalGroupGetMembers');
        @NetApiBufferFree :=
GetProcAddress(NetApiDllHandle,'NetApiBufferFree');
        if (@NetLocalGroupGetMembers<>nil) and (@NetApiBufferFree<>nil) then
        begin
          ListUsers := TStringList.Create;
          ListGroups := TStringList.Create;
          try
            GetLocalGroupUsers('', 'Administrators'); // prazdny retazec je
lokalny stroj
            GetLocalGroupUsers('', 'Power Users');
            GetLocalGroupUsers('', 'Users');
            L_privilege.Caption :=
ListGroups.Strings[ListUsers.IndexOf(L_username.Caption)];
          finally
            ListUsers.Free;
            ListGroups.Free;
          end;
        end;
      end;
    end;
  end;
end;

function GetEnvVar(const Name:String):String;
var L:Dword;
begin
  L:=GetEnvironmentVariable(PChar(Name),nil,0);
  SetString(Result,nil,L);
  if GetEnvironmentVariable(PChar(Name),PChar(Result),L) <> L-1 then
  begin
    RaiseLastWin32Error;
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if NetApiDllHandle<>0 then
    FreeLibrary(NetApiDllHandle);
end;

end.

Je to jen testovaci programek pro reseni problemu v prechazajicim sub.

> -----Original Message-----
> From: delphi-l-owner@clexpert.cz [mailto:delphi-l-owner@clexpert.cz]On
> Behalf Of Ing. Igor Vodicka
>
> Jinymi slovy, potrebuji pri spusteni programu zjistit (na Win 9X
> test nemusi
> probehnout), ze aktualni uzivatel je minimalne "power users".
> Program totiz
> potrebuje prava pro zapis do slozek v progam files, kde ja nainstalovany.
>

Pokud programek spustim na Win2000 nabo XP vse je OK. Na Win 98 se objevi
hlaska:

Win32 Error. Code 203. System nenalezl zadanou systemovou promennou.

Hlaska se zrejme tyka promenne LOCALGROUP_MEMBERS_INFO_1 a funkce
NetLocalGroupGetMembers, ktere nejsou na Win 9X dostupne.

Existuje nejaky ekvivalent pro Win 9X nebo nevite nekdo jak z toho ven?

Ing. Igor Vodicka
informacni systemy
Nakladatelstvi Sagit
Tel.: 59 6786 001
HTTP://www.sagit.cz/

Odpovedá: Ondrej Kelle

26. 8. 2004 9:39

         aktualnim uzivateli?
[snip]
> Pokud programek spustim na Win2000 nabo XP vse je OK. Na Win
> 98 se objevi hlaska:
>
> Win32 Error. Code 203. System nenalezl zadanou systemovou promennou.

Zaujimave, na ktorom riadku sa objavi ta hlaska?
Nemas nahodou este niekde v projekte zabudnute tie staticke deklaracie?

> Hlaska se zrejme tyka promenne LOCALGROUP_MEMBERS_INFO_1 a funkce
> NetLocalGroupGetMembers, ktere nejsou na Win 9X dostupne.

To asi nie. Ten kod v pripade, ze bezi na Windows 9x, netapi32.dll vobec
nepouziva.

HTH
TOndrej


Odpovedá: Ing. Igor Vodicka

26. 8. 2004 10:18

         aktualnim uzivateli?


> -----Original Message-----
> From: delphi-l-owner@clexpert.cz [mailto:delphi-l-owner@clexpert.cz]On
> Behalf Of Ondrej Kelle

> > Win32 Error. Code 203. System nenalezl zadanou systemovou promennou.
>
> Zaujimave, na ktorom riadku sa objavi ta hlaska?

Problem trochu je, ze programuji na Win 2000 (zde je vse OK). Programek pak
testuji i na Win 98 a zde je problem.
Udelal jsem si za kazdym radkem vlastni hlasku, ze tuda program projel.

program Project1;

uses
  Forms, Dialogs,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

begin
  ShowMessage('START');
  Application.Initialize;
  ShowMessage('Application.Initialize;');
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Obe hlasky se objevily, ale hlasky v CreateForm uz ne, nastala chyba. Jde to
neja otestovat kde to krachne, kdyz na PC s Win 98 nemam Deplhi (delam v D5
ent).

> Nemas nahodou este niekde v projekte zabudnute tie staticke deklaracie?
>
Ne, nejsou tam.

Ing. Igor Vodicka
informacni systemy
Nakladatelstvi Sagit
Tel.: 59 6786 001
HTTP://www.sagit.cz/

Odpovedá: Ondrej Kelle

26. 8. 2004 10:25

         aktualnim uzivateli?
>> Win32 Error. Code 203. System nenalezl zadanou systemovou
>> promennou.

Aha, tak som si to precital pozornejsie  
203 = ERROR_ENVVAR_NOT_FOUND

to bude ten riadok
  L_username.Caption := GetEnvVar('USERNAME');

skratka na tych Windows taka premenna nie je definovana.
Tu si sa na vlastnej kozi presvedcil o tom, ze je lepsie pouzit API funkciu,
ak taka na dany ucel existuje.

GetUserName by mala fungovat vsade rovnako.

HTH
TOndrej


Odpovedá: Ing. Igor Vodicka

26. 8. 2004 12:35

         aktualnim uzivateli?
Super, to bylo presne ono. Na zjisteni aktualniho uzivatele jsem nakonec
pouzil funkci GetLocalUserName z JCL a uz je to OK.

Diky

Ing. Igor Vodicka
informacni systemy
Nakladatelstvi Sagit
Tel.: 59 6786 001
HTTP://www.sagit.cz/

> -----Original Message-----
> From: delphi-l-owner@clexpert.cz [mailto:delphi-l-owner@clexpert.cz]On
> Behalf Of Ondrej Kelle
>
> >> Win32 Error. Code 203. System nenalezl zadanou systemovou
> >> promennou.
>
> Aha, tak som si to precital pozornejsie  
> 203 = ERROR_ENVVAR_NOT_FOUND
>
> to bude ten riadok
> L_username.Caption := GetEnvVar('USERNAME');
>
> skratka na tych Windows taka premenna nie je definovana.
> Tu si sa na vlastnej kozi presvedcil o tom, ze je lepsie pouzit
> API funkciu,
> ak taka na dany ucel existuje.
>